# -*- coding: utf-8 -*-

from ip.opdef import ExecOp, AluOpCode
from .hw_defs import VARS
from .package import NanoOpTypes


HANA_EOPS = {
    'add': [ExecOp, ['op_code', AluOpCode.ADD], NanoOpTypes.EopsName, None,
             [['alu', 'alu', 0],
              ['pid', 'peer_id', pow(2, VARS.num_of_peer) - 1],

              ['dst', 'dst_addr'],
              ['dst_inc', 'dst_increase', 0],
              ['offset', 'dst_enable_offset', False],

              ['src0', 'src_addr_0'],
              ['ain0', 'src_wait_aluin_0', False],
              ['wait0', 'src_wait_passin_0', False],
              ['offset0', 'src_enable_offset_0', False],

              ['src1', 'src_addr_1'],
              ['ain1', 'src_wait_aluin_1', False],
              ['wait1', 'src_wait_passin_1', False],
              ['offset1', 'src_enable_offset_1', False]],
             [['dst_peer_id', 0],
              ['dst_stride', 1],
              ['dst_sb', False],
              ['len_limit', 1],
              ['src_stride_0', 1],
              ['src_stride_1', 1],
              ['src_limit_0', 'op.src_addr_0 + 1'],
              ['src_limit_1', 'op.src_addr_1 + 1']]],
    'sub': [ExecOp, ['op_code', AluOpCode.SUB], NanoOpTypes.EopsName, None,
             'add', 'add'],
    'mul': [ExecOp, ['op_code', AluOpCode.MUL], NanoOpTypes.EopsName, None,
             'add', 'add'],
    'div': [ExecOp, ['op_code', AluOpCode.DIV], NanoOpTypes.EopsName, None,
             'add', 'add'],
    'add_v': [ExecOp, ['op_code', AluOpCode.ADD], NanoOpTypes.EopsName, None,
               [['alu', 'alu', 0],
                ['pid', 'peer_id', pow(2, VARS.num_of_peer) - 1],

                ['dst', 'dst_addr'],
                ['dst_inc', 'dst_increase', 0],
                ['dst_stride', 'dst_stride', 1],
                ['offset', 'dst_enable_offset', False],
                ['count', 'len_limit'],

                ['src0', 'src_addr_0'],
                ['ain0', 'src_wait_aluin_0', False],
                ['wait0', 'src_wait_passin_0', False],
                ['stride0', 'src_stride_0', 1],
                ['offset0', 'src_enable_offset_0', False],
                ['limit0', 'src_limit_0', 'op.src_addr_0 + op.len_limit * op.src_stride_0'],

                ['src1', 'src_addr_1'],
                ['ain1', 'src_wait_aluin_1', False],
                ['wait1', 'src_wait_passin_1', False],
                ['stride1', 'src_stride_1', 1],
                ['offset1', 'src_enable_offset_1', False],
                ['limit1', 'src_limit_1', 'op.src_addr_1 + op.len_limit * op.src_stride_1'],],
              [['dst_peer_id', 0],
               ['dst_sb', False]]],
    'sub_v': [ExecOp, ['op_code', AluOpCode.SUB], NanoOpTypes.EopsName, None,
               'add_v', 'add_v'],
    'mul_v': [ExecOp, ['op_code', AluOpCode.MUL], NanoOpTypes.EopsName, None,
               'add_v', 'add_v'],
    'div_v': [ExecOp, ['op_code', AluOpCode.DIV], NanoOpTypes.EopsName, None,
               'add_v', 'add_v'],
    'wait': [ExecOp, ['op_code', AluOpCode.WAIT], NanoOpTypes.EopsName, None,
              [['alu', 'alu', 0],
               ['pid', 'peer_id', pow(2, VARS.num_of_peer) - 1],

               ['src', 'src_addr_0'],
               ['src_offset', 'src_enable_offset_0', False]],
              [['len_limit', 1],
               ['dst_stride', 0],
               ['dst_addr', 0],
               ['dst_increase', 0],
               ['dst_peer_id', 0],
               ['dst_enable_offset', False],
               ['dst_sb', False],

               ['src_stride_0', 1],
               ['src_wait_passin_0', False],
               ['src_wait_aluin_0', False],
               ['src_limit_0', 'op.src_addr_0 + 1'],

               ['src_addr_1', 0],
               ['src_wait_passin_1', False],
               ['src_wait_aluin_1', False],
               ['src_enable_offset_1', 0],
               ['src_stride_1', 0],
               ['src_limit_1', 0]]],
    'wait_v': [ExecOp, ['op_code', AluOpCode.WAIT], NanoOpTypes.EopsName, None,
              [['alu', 'alu', 0],
               ['pid', 'peer_id', pow(2, VARS.num_of_peer) - 1],
               ['count', 'len_limit'],

               ['src', 'src_addr_0'],
               ['src_stride', 'src_stride_0', 1],
               ['src_offset', 'src_enable_offset_0', False]],
              [['dst_stride', 0],
               ['dst_addr', 0],
               ['dst_increase', 0],
               ['dst_peer_id', 0],
               ['dst_enable_offset', False],
               ['dst_sb', False],

               ['src_wait_passin_0', False],
               ['src_wait_aluin_0', False],
               ['src_limit_0', 'op.src_addr_0 + 1'],

               ['src_addr_1', 0],
               ['src_wait_passin_1', False],
               ['src_wait_aluin_1', False],
               ['src_enable_offset_1', 0],
               ['src_stride_1', 0],
               ['src_limit_1', 0]]],
    'put': [ExecOp, ['op_code', AluOpCode.PUT], NanoOpTypes.EopsName, None,
             [['dst_pid', 'dst_peer_id'],
              ['dst', 'dst_addr'],
              ['dst_sb', 'dst_sb', False],
              ['dst_inc', 'dst_increase', 0],

              ['src_pid', 'peer_id'],
              ['src_alu', 'alu', 0],
              ['src', 'src_addr_0'],
              ['src_wait', 'src_wait_passin_0', False],
              ['src_ain', 'src_wait_aluin_0', False],
              ['src_offset', 'src_enable_offset_0', False]],
            [['len_limit', 1],
             ['dst_enable_offset', False],
             ['dst_stride', 1],

             ['src_stride_0', 1],
             ['src_limit_0', 'op.src_addr_0 + 1'],

             ['src_addr_1', 'op.src_addr_0'],
             ['src_wait_passin_1', False],
             ['src_wait_aluin_1', False],
             ['src_enable_offset_1', 'op.src_enable_offset_0'],
             ['src_stride_1', 1],
             ['src_limit_1', 'op.src_addr_0 + 1']]],
    'put_v': [ExecOp, ['op_code', AluOpCode.PUT], NanoOpTypes.EopsName, None,
             [['dst_pid', 'dst_peer_id'],
              ['dst', 'dst_addr'],
              ['dst_inc', 'dst_increase', 0],
              ['dst_stride', 'dst_stride', 1],
              ['dst_sb', 'dst_sb', False],
              ['count', 'len_limit'],

              ['src_pid', 'peer_id'],
              ['src_alu', 'alu', 0],
              ['src', 'src_addr_0'],
              ['src_wait', 'src_wait_passin_0', False],
              ['src_ain', 'src_wait_aluin_0', False],
              ['src_stride', 'src_stride_0', 1],
              ['src_offset', 'src_enable_offset_0', False],
              ['src_limit', 'src_limit_0', 'op.src_addr_0 + op.len_limit']],
            [['dst_enable_offset', False],

             ['src_addr_1', 'op.src_addr_0'],
             ['src_wait_passin_1', False],
             ['src_wait_aluin_1', False],
             ['src_enable_offset_1', 'op.src_enable_offset_0'],
             ['src_stride_1', 1],
             ['src_limit_1', 'op.src_addr_0 + 1']]],
    'halt': [ExecOp, ['op_code', AluOpCode.HALT], NanoOpTypes.EopsName, None,
             [],
             [['alu', pow(2, VARS.num_of_alu) - 1],
              ['peer_id', pow(2, VARS.num_of_peer) - 1],

              ['dst_sb', False],
              ['len_limit', 0],
              ['dst_addr', 0],
              ['dst_increase', 0],
              ['dst_enable_offset', False],
              ['dst_peer_id', 0],
              ['dst_stride', 0],

              ['src_addr_0', 0],
              ['src_wait_passin_0', False],
              ['src_wait_aluin_0', False],
              ['src_enable_offset_0', False],
              ['src_stride_0', 0],
              ['src_limit_0', 0],

              ['src_addr_1', 0],
              ['src_wait_passin_1', False],
              ['src_wait_aluin_1', False],
              ['src_enable_offset_1', False],
              ['src_stride_1', 0],
              ['src_limit_1', 0]]]
}